import ScriptTool_IIconSVG from "IIconSVG";
import ScriptTool_ICalculator from "ICalculator";

let iconsvg: IIconSVG = new ScriptTool_IIconSVG().GetCase();
let calculator: ICalculator = new ScriptTool_ICalculator().GetCase();

namespace Projects.MemoryPalaceTrainingProgram.Day003_ShultGrid {
    /** 游戏对象 */
    export class Game {
        private readonly config: GameConfig;

        constructor(config: GameConfig) {
            this.config = config;
        }

        private x: number;
        private y: number;
        public ReConfigXY(x: number, y: number) {
            this.x = x;
            this.y = y;
        }

        public SelectItem(item: number): boolean {
            let self = this;
            if (self.timer_interval_sign === null) {
                self.config.notifyCallback(2, "请点击开始, 进行游戏");
                return false;
            }
            let value = calculator.Add(self.sign, 1);
            if (value !== item) {
                self.config.notifyCallback(2, "点击错误");
                return false;
            }
            self.sign = value;
            if (self.sign === self.result) {
                self.config.notifyCallback(0, "挑战成功");
                self.End();
            }
            return true;
        }

        private minute: number = 0;
        private second: number = 0;
        private millisecond: number = 0;
        private sign: number;
        private result: number;
        private timer_interval_sign: number = null;
        /** 开始游戏 */
        public Start() {
            let self = this;

            self.MakeZeroResult();

            const interval: number = 100;
            self.timer_interval_sign = setInterval(function () {
                self.millisecond = calculator.Add(self.millisecond, interval);

                let value = parseInt(calculator.Div(self.millisecond, 1000).toString());
                self.second = calculator.Add(self.second, value);
                self.millisecond %= 1000;

                value = parseInt(calculator.Div(self.second, 60).toString());
                self.minute = calculator.Add(self.minute, value);
                self.second %= 60;

                self.config.drawTimerCallback(self.minute, self.second, self.millisecond);
            }, interval);
            self.config.processCallback(1);
        }
        /** 重新渲染游戏图表 */
        public ReDrawTables() {
            let self = this;
            self.End();

            self.MakeZeroResult();

            let tables = self.GenerateTables(self.x, self.y);
            let size = calculator.getRandomInt({ min: 10, max: 20 });
            tables = self.DisturbanceTables(tables, size);
            self.config.drawTableCallback(tables);
        }
        /** 归零结果 */
        private MakeZeroResult() {
            let self = this;

            self.minute = 0;
            self.second = 0;
            self.millisecond = 0;
            self.config.drawTimerCallback(self.minute, self.second, self.millisecond);
            self.sign = 0;
            self.result = calculator.Mul(self.x, self.y);
        }
        /** 结束游戏 */
        public End() {
            let self = this;
            clearInterval(self.timer_interval_sign);
            self.timer_interval_sign = null;
            self.config.processCallback(0);
        }

        /**
         * 生成表格
         * @param x 横向列数
         * @param y 纵向行数
         * @returns 表格数据
         */
        public GenerateTables(x: number, y: number): number[][] {
            let list: number[][] = [];
            let number = 0;
            for (let y_index = 0; y_index < y; y_index++) {
                let arr = [];
                for (let x_index = 0; x_index < x; x_index++) {
                    arr.push(++number);
                }
                list.push(arr);
            }
            return list;
        }

        /**
         * 打乱表格顺序
         * @param list 表格数据
         * @param size 打乱次序
         * @returns 结果表格数据
         */
        public DisturbanceTables(list: number[][], size: number): number[][] {
            let self = this;
            for (let index = 0; index < size; index++) {
                let coordinate_1 = self.get_table_random_position(list);
                let coordinate_2 = self.get_table_random_position(list);
                let value = list[coordinate_1.y][coordinate_1.x];
                list[coordinate_1.y][coordinate_1.x] = list[coordinate_2.y][coordinate_2.x];
                list[coordinate_2.y][coordinate_2.x] = value;
            }
            return list;
        }

        private get_table_random_position(list: number[][]): { x: number; y: number } {
            let y = calculator.getRandomInt({ min: 0, max: list.length - 1 });
            let x = calculator.getRandomInt({ min: 0, max: list[y].length - 1 });
            return { x, y };
        }

        /**
         * 获取棋盘规则配置
         * @returns
         */
        public GetIRegularChessboards(): IRegularChessboard[] {
            let arr: IRegularChessboard[] = [
                {
                    x: 3,
                    y: 3,
                    scores: [
                        { name: "顶尖", max: 1.8 },
                        { name: "极好", min: 1.8, max: 2.5 },
                        { name: "好", min: 2.5, max: 3.6 },
                        { name: "正常", min: 3.6, max: 4.2 },
                        { name: "需要训练", min: 4.2 },
                    ],
                },
                {
                    x: 4,
                    y: 4,
                    scores: [
                        { name: "顶尖", max: 4.8 },
                        { name: "极好", min: 4.8, max: 7 },
                        { name: "好", min: 7, max: 11 },
                        { name: "正常", min: 11, max: 15 },
                        { name: "需要训练", min: 15 },
                    ],
                },
                {
                    x: 5,
                    y: 5,
                    scores: [
                        { name: "顶尖", max: 8.7 },
                        { name: "极好", min: 8.7, max: 14 },
                        { name: "好", min: 14, max: 18.5 },
                        { name: "正常", min: 18.5, max: 25 },
                        { name: "需要训练", min: 25 },
                    ],
                },
                {
                    x: 6,
                    y: 6,
                    scores: [
                        { name: "顶尖", max: 23 },
                        { name: "极好", min: 23, max: 30 },
                        { name: "好", min: 30, max: 44 },
                        { name: "正常", min: 44, max: 52 },
                        { name: "需要训练", min: 52 },
                    ],
                },
                {
                    x: 7,
                    y: 7,
                    scores: [
                        { name: "顶尖", max: 49 },
                        { name: "极好", min: 49, max: 74 },
                        { name: "好", min: 74, max: 88 },
                        { name: "正常", min: 88, max: 120 },
                        { name: "需要训练", min: 120 },
                    ],
                },
            ];
            return arr;
        }

        public GenerateRegularChessboardScoreDescribe(config: IRegularChessboard) {
            let self = this;
            for (let score_i = 0; score_i < config.scores.length; score_i++) {
                let scores = config.scores[score_i];
                if (!scores.describe) {
                    scores.describe = self.GenerateScoreDescribe(scores);
                }
                config.scores[score_i] = scores;
            }
        }
        public GenerateScoreDescribe(score: IRegularScore) {
            let self = this;
            if (!score.min && !score.max) {
                return "<无限制> : " + score.name;
            }
            if (!score.max) {
                return self.to_format_time_desc(score.min) + "以内 : " + score.name;
            }
            if (!score.min) {
                return self.to_format_time_desc(score.max) + "以上 : " + score.name;
            }
            return (
                self.to_format_time_desc(score.min) + " ~ " + self.to_format_time_desc(score.max) + " : " + score.name
            );
        }

        private to_format_time_desc(second: number) {
            var minute = parseInt(calculator.Div(second, 60).toString());
            second = second % 60;
            var r = "";
            if (minute > 0) {
                r += minute + "分";
            }
            if (second > 0) {
                r += second + "秒";
            }
            return r;
        }
    }

    interface GameConfig {
        /**
         * 游戏进度回调
         * @param sign 0:结束游戏 1:开始游戏
         */
        processCallback: (sign: number) => void;
        /**
         * 渲染时间计时器回调处理
         * @param minute 分钟
         * @param second 秒
         * @param millisecond 毫秒
         */
        drawTimerCallback: (minute: number, second: number, millisecond: number) => void;
        /**
         * 渲染游戏图标回调处理
         * @param tables 游戏图表配置
         */
        drawTableCallback: (tables: number[][]) => void;
        /**
         * 通知回调
         * @param sign 0:游戏完成 1:游戏失败 2:操作警告
         * @param message 通知内容
         */
        notifyCallback: (sign: number, message: string) => void;
    }
    /** 规则棋盘 */
    interface IRegularChessboard {
        x: number;
        y: number;
        scores: IRegularScore[];
    }
    /** 规则评分 */
    interface IRegularScore {
        /** 最小范围对象 (秒) */
        min?: number;
        /** 最大范围对象 (秒) */
        max?: number;
        /** 评价名称 (顶尖/极好/好/正常/需要训练) */
        name: string;
        /** 描述 */
        describe?: string;
    }
}

export async function Run() {
    // 在线: 舒尔特方格训练: https://schultegrid.com/
    iconsvg.onload();

    let artTemplate = await import(ToResourceURL(EResourceID.LibraryOne, "/Scripts/art-template.js"));

    var Span_minute = $("#IDHTML_Span_minute");
    var Span_second = $("#IDHTML_Span_second");
    var Span_millisecond = $("#IDHTML_Span_millisecond");

    var config = {
        processCallback: function (sign) {
            // 0:结束游戏
            if (sign === 0) {
                $(".assembly_end").show();
                $(".assembly_start").hide();
            }
            // 1:开始游戏
            if (sign === 1) {
                $(".assembly_end").hide();
                $(".assembly_start").show();
            }
        },
        drawTimerCallback: function (minute, second, millisecond) {
            Span_minute.html(minute.toString().padStart(2, "0"));
            Span_second.html(second.toString().padStart(2, "0"));
            Span_millisecond.html(millisecond.toString().padStart(3, "0").substring(0, 2));
        },
        drawTableCallback: function (tables) {
            var tempalte = $("#IDHTML_Template_ShultGrid_table_row");
            var html = $(
                artTemplate.render(tempalte.html(), {
                    tables: tables,
                })
            );
            var box = $("#IDHTML_Box_ShultGrid_table");
            box.empty();
            box.append(html);
        },
        notifyCallback: function (sign, message) {
            var sign_msg = "";
            switch (sign) {
                case 0:
                    sign_msg = "成功";
                    break;
                case 1:
                    sign_msg = "失败";
                    break;
                case 2:
                    sign_msg = "警告";
                    break;
                default:
                    sign_msg = "<未知>:" + sign;
                    break;
            }
            alert("游戏提示: " + sign_msg);
            // $.messager.show({
            //     title: "游戏提示: " + sign_msg,
            //     msg: message,
            //     timeout: 1000,
            //     showType: "slide",
            // });
        },
    };

    let game = new Projects.MemoryPalaceTrainingProgram.Day003_ShultGrid.Game(config);
    (window as any).game = game;

    game.ReConfigXY(3, 3);
    game.ReDrawTables();

    (window as any).selected_grid = function (el) {
        var value = $(el).attr("data-number");
        if (game.SelectItem(parseInt(value))) {
            $("#IDHTML_Box_ShultGrid_table").find(".grid").removeClass("selected");
            $(el).addClass("selected");
        }
    };

    var regularChessboards = game.GetIRegularChessboards();
    set_page_choice();
    function set_page_choice() {
        var tempalte = $("#IDHTML_Template_ShultGrid_choice");
        var box = $("#IDHTML_Box_ShultGrid_choice");
        box.empty();
        for (var index = 0; index < regularChessboards.length; index++) {
            var c = regularChessboards[index];
            var html = $(artTemplate.render(tempalte.html(), c));
            box.append(html);
        }
        if (regularChessboards.length > 0) {
            var x = regularChessboards[0].x;
            var y = regularChessboards[0].y;
            game.ReConfigXY(3, 3);
            game.ReDrawTables();
            set_page_score_content(x, y);
        }
    }
    function selected_config(el) {
        var x = parseInt($(el).attr("data-x"));
        var y = parseInt($(el).attr("data-y"));
        game.ReConfigXY(x, y);
        game.ReDrawTables();
        set_page_score_content(x, y);
    }
    (window as any).selected_config = selected_config;
    function set_page_score_content(x, y) {
        var config = null;
        for (var index = 0; index < regularChessboards.length; index++) {
            var c = regularChessboards[index];
            if (c.x == x && c.y == y) {
                config = c;
                break;
            }
        }
        if (!config) {
            return;
        }
        var tempalte = $("#IDHTML_Template_ShultGrid_score_content");
        game.GenerateRegularChessboardScoreDescribe(config);
        console.log("config:", config);
        var html = $(artTemplate.render(tempalte.html(), config));
        var box = $("#IDHTML_Box_ShultGrid_score_content");
        box.empty();
        box.append(html);
    }
}
